"""
主题: 拆解Python字节码
问题: 你想通过将你的代码反编译成低级的字节码来查看它底层的工作机制。
提示 : 
"""
import dis

def countdown(n):
    while n > 0:
        print('T-minus', n)
        n -= 1
    print('Blastoff!')

import opcode

def generate_opcodes(codebytes):
    extended_arg = 0
    i = 0
    n = len(codebytes)
    while i < n:
        op = codebytes[i]
        i += 1
        if op >= opcode.HAVE_ARGUMENT:
            oparg = codebytes[i] + codebytes[i + 1] * 256 + extended_arg
            extended_arg = 0
            i += 2
            if op == opcode.EXTENDED_ARG:
                extended_arg = oparg * 65536
                continue
        else:
            oparg = None
        yield (op, oparg)

def add(x, y):
    return x + y

def recipe1():
    dis.dis(countdown)

def recipe2():
    c = countdown.__code__.co_code
    import opcode
    print(f"{opcode.opname[c[0]]= }")
    print(f"{opcode.opname[c[2]]= }")

def recipe3():
    for op, oparg in generate_opcodes(countdown.__code__.co_code):
        print(op, opcode.opname[op], oparg)

def recipe4():
    '''替换任何你想要替换的函数的原始字节码'''
    c = add.__code__
    print(f"{c = }")
    print(f"{c.co_code = }")


    import types
    newbytecode = b'xxxxxxx'
    nc = types.CodeType(c.co_argcount, c.co_posonlyargcount, c.co_kwonlyargcount,
        c.co_nlocals, c.co_stacksize, c.co_flags, newbytecode, c.co_consts,
        c.co_names, c.co_varnames, c.co_filename, c.co_name,
        c.co_firstlineno, c.co_lnotab)
    add.__code__ = nc
    c = add.__code__
    print(f"{c = }")
    print(f"{c.co_code = }")

    try:
        add(2,3)
    except SystemError as e:
        print(e)  

def main():
    print('recipe1'.center(20, '*'))
    recipe1()
    print('recipe2'.center(20, '*'))
    recipe2()    
    print('recipe3'.center(20, '*'))
    recipe3()  
    print('recipe4'.center(20, '*'))
    recipe4() 

if __name__ == '__main__':
    main()    